﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Linq.Expressions;

namespace JackyCode.Mock.Extensions
{
    public static class ExpressionExtensions
    {
        public static MethodInfo GetMethodInfo(this LambdaExpression expression)
        {
                MethodCallExpression methodCallExpression = expression.Body as MethodCallExpression;
                return methodCallExpression.Method;
        }

        public static MethodData ExtractAsMethodData(this LambdaExpression expression)
        {
            return new MethodData(expression.GetArgumentDetails(), expression.GetMethodInfo());
        }

        private static IList<ArgumentDetail> GetArgumentDetails(this LambdaExpression expression)
        {
            IList<ArgumentDetail> results = new List<ArgumentDetail>();
            ParameterInfo[] pis = expression.GetMethodInfo().GetParameters();

            for (int index = 0; index < pis.Length; index++)
            {
                results.Add(new ArgumentDetail
                    {
                        IsNotOut = !pis[index].IsOut,
                        Value = GetArgumentVal((MethodCallExpression)expression.Body, index)
                    }
                );
            }
            return results;
        }

        private static object GetArgumentVal(MethodCallExpression mce, int index)
        {
            Expression argumentExp = mce.Arguments[index];

            if (argumentExp is ConstantExpression)
            {
                return ((ConstantExpression)argumentExp).Value;
            }
            else if (argumentExp is MemberExpression)
            {
                return GetMemberExpFieldVal(argumentExp);
            }
            return null;
        }

        private static object GetMemberExpFieldVal(Expression argumentExp)
        {
            MemberExpression me = (MemberExpression)argumentExp;
            object instance = ((ConstantExpression)me.Expression).Value;
            FieldInfo fieldInfo = instance.GetType().GetField(me.Member.Name);
            return fieldInfo.GetValue(instance);
        }

    }


}
